from time import sleep
from math import floor
from ctypes import *

class EDMRmagnet:
    def __init__(self,test=False):
        self.isTest=test
        self.device_id=c_int()#create a buffer(4)
        self.ret=c_int(0)
        self.board_no=c_int(0)
        self.base_no=c_int(2)
        self.fRet=c_int(0)
        self.RESET = c_int(7)
        self.DATA_CODE = c_int(2)
        self.BINARY = c_int(0)
        self.DA_CH0_MODE = c_int(0)
        self.DA_CH1_MODE = c_int(1)
        self.DA_CH0_DATA_LO = c_int(4)
        self.DA_CH0_DATA_HI = c_int(5)
        self.DA_CH1_DATA_LO = c_int(6)
        self.DA_CH1_DATA_HI = c_int(7)
        self.iobase=c_int()
        self.DA_BUSY=c_int(2)
        self.END_OF_BUSY=4
        self.maxvoltage=10 # in Volt
        self.dll=windll.LoadLibrary("Port_2k")
    
    def OpenRessource(self):
        self.dll.Open_Driver(byref(self.device_id))
        self.dll.Start_Driver(self.board_no, self.base_no,byref(self.iobase))
        self.dll.ReadByte(self.iobase, self.RESET)
        self.dll.WriteByte(self.iobase, self.DATA_CODE, self.BINARY)
        self.dll.WriteByte(self.iobase, self.DA_CH0_MODE, c_int32(26))#'%(n)X'%{"n":26}
        self.dll.WriteByte(self.iobase, self.DA_CH1_MODE, c_int32(26))#'%(n)X'%{"n":26}
        self.SetMagneticField(0) #in gauss
    
    def CloseRessource(self):
        self.SetMagneticField(0) #in gauss
    
    def SetMagneticField(self,field,unit="gauss"):#field in gauss
        #check unit
        if unit in ["gauss","G","Gauss"]:
            mag=field
        elif unit in ["mT","millitesla","MilliTesla","Millitesla","milliTesla"]:
            mag=field*10
        elif unit in ["militesla","MiliTesla","Militesla","miliTesla"]:
            print "Spelling should be millistesla, automatically set to it."
            mag=field*10
        elif unit in ["T","tesla","Tesla"]:
            mag=field*10000
        
        v=((10 / 15.0) * (0.00293 + 0.01 * (mag * 1.2))) #conversion to voltage
        # Security
        if v>self.maxvoltage:
            v=self.maxvoltage
            print "Maximum voltage reached: set to %d V",self.maxvoltage
        elif v<-self.maxvoltage:
            v=-self.maxvoltage
            print "Minimum voltage reached: set to -%d V",self.maxvoltage
        v1=v*100000 #unit of v1 is 10microvolts
        v2=int(v1/2000000.0 * 65535 + 32768) #symmetry around 32768

        data=hex(v2)[-4:] #data is "XXYY" where X and Y are hex
        data1=c_int(int(data[2:],16)) #YY
        data2=c_int(int(data[:2],16)) #XX
        self.dll.WriteByte(self.iobase, self.DA_CH0_DATA_LO, data1) #YY as lowest weighted bits
        self.dll.WriteByte(self.iobase, self.DA_CH0_DATA_HI, data2) #XX as highest weighted bits
        
        #Don't know why this loop should be here. The condition is never satisfied as far as we know.
        while ((self.dll.ReadByte(self.iobase, self.DA_BUSY)&self.END_OF_BUSY) == self.END_OF_BUSY):
            pass

if __name__ == "__main__":
    magnet=EDMRmagnet(False)
    magnet.OpenRessource()
    magnet.SetMagneticField(10, "gauss")
    sleep(5)
    magnet.CloseRessource()